package threadsdemo;

import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BlockingQueue {
    private List queue = new LinkedList<>();

    public void add(Object element) {
        synchronized(queue) {
            queue.add(element);
            queue.notifyAll();
        }
    }

    public Object remove() {
        synchronized(queue) {
            while (queue.isEmpty()) try {
                queue.wait();
            } catch (InterruptedException e) {
                return null;
            }
            return queue.remove(0);
        }
    }


    public static void main(String[] args) {
        System.out.println((new BlockingQueue()).remove());
    }
}


class Account {
    private int amount;

    public void transfer(Account subj) {
        synchronized (this) {
            synchronized (subj) {
                this.amount--;
                subj.amount++;
            }
        }
    }
}



class DefectThread extends Thread {
    private boolean isStopped;

    public void setStopped(boolean isStopped) {
        this.isStopped = isStopped;
    }

    public synchronized boolean isStopped() {
        return isStopped;
    }

    @Override
    public void run() {
        while(!isStopped()) {

        }
    }

    public static void main(String[] args) throws InterruptedException {
        DefectThread t = new DefectThread();
        t.start();
        Thread.sleep(1000);
        t.setStopped(true);
    }
}

class Counter {
    private int counter;

    public void increment() {
        counter++;
    }
}

class FunctionalChatServer {
    public static void main(String[] args) {
        new Thread(() -> {
            try(ServerSocket ss = new ServerSocket(9999)) {
                Set<Socket> sockets = new HashSet<>();
                while(true) {
                    Socket readSocket;
                    sockets.add(readSocket = ss.accept());
                    new Thread(() -> {
                        DataInputStream input = null;
                        try {
                            input = new DataInputStream(readSocket.getInputStream());
                            while (true) {
                                String message = input.readUTF();
                                new Thread(() -> {
                                    for(Socket writeSocket : sockets) {
                                        try {
                                            new DataOutputStream(writeSocket.getOutputStream()).writeUTF(message);
                                        } catch (IOException e) { 
                                          e.printStackTrace(); 
                                          sockets.remove(writeSocket);
                                        }
                                    }
                                }).start();
                            }
                        } catch (IOException e) { e.printStackTrace(); }
                    }).start();
                }
            }catch (IOException e) { e.printStackTrace(); }
        }).start();
    }
}















